package cn.xzc.job.pojo;

import cn.xzc.job.util.ReflectUtil;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.UndeclaredThrowableException;
import java.util.Objects;

/**
 * 处理无参数调用方法：统一异常处理方式[异常不会打断后续任务的执行：checkException转runtimeException]---runnable
 *
 * @author xzc
 * 当前时间 2024-02-12 21:30:00
 */
public class ScheduledMethodRunnable implements Runnable {

    /**
     * 要执行的方法对应的对象
     */
    private final Object target;

    /**
     * 要具体执行的方法
     */
    private final Method method;


    /**
     * Create a {@code ScheduledMethodRunnable} for the given target instance,
     * calling the specified method.
     *
     * @param target the target instance to call the method on
     * @param method the target method to call
     */
    public ScheduledMethodRunnable(Object target, Method method) {
        this.target = target;
        this.method = method;
    }

    /**
     * Create a {@code ScheduledMethodRunnable} for the given target instance,
     * calling the specified method by name.
     *
     * @param target     the target instance to call the method on
     * @param methodName the name of the target method
     * @throws NoSuchMethodException if the specified method does not exist
     */
    public ScheduledMethodRunnable(Object target, String methodName) throws NoSuchMethodException {
        this.target = target;
        this.method = target.getClass().getMethod(methodName);
    }


    /**
     * Return the target instance to call the method on.
     */
    public Object getTarget() {
        return this.target;
    }

    /**
     * Return the target method to call.
     */
    public Method getMethod() {
        return this.method;
    }


    @Override
    public void run() {
        try {
            ReflectUtil.setAccessible(this.method);
            //调用方法：静态方法允许target为空
            this.method.invoke(this.target);
        } catch (InvocationTargetException ex) {
            ReflectUtil.rethrowRuntimeException(ex.getTargetException());
        } catch (IllegalAccessException ex) {
            throw new UndeclaredThrowableException(ex);
        }
    }

    @Override
    public String toString() {
        return this.method.getDeclaringClass().getName() + "." + this.method.getName();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (!(o instanceof ScheduledMethodRunnable)) {
            return false;
        }
        ScheduledMethodRunnable that = (ScheduledMethodRunnable) o;
        return Objects.equals(target, that.target) && Objects.equals(method, that.method);
    }

    @Override
    public int hashCode() {
        return Objects.hash(target, method);
    }
}